﻿using ACC.Business;
using ACC.Business.Process;
using ACC.Business.Utils;
using ACC.Data;
using ACC.Data.ACCLog;
using ACC.Data.Comm;
using ACC.Data.Entities.Mes;
using ACC.Data.Line;
using ACC.Device;
using ACC.Device.Client;
using ACC.Interface.Extensions;
using ACC.LineDevice.KukaPack;
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;

namespace Script
{
    /// <summary>
    /// 下箱体上线， 人工
    /// OP L1P01010, L1P01011, L1P01012
    /// </summary>
    public class L1P01010 : StnProcessKukaClientWithPLC
    {
        int PlannedQty = 0;
        string OrderNo = string.Empty;

        public L1P01010(StnRunningData data)
            : base(data)
        {
            Position = string.Empty;
            IsACCReport = true;
            IsReport = true;
            // 不用基类的处理托盘逻辑
            IsPalletRelationSN = false;
            PlcName = "PLC130";

            data.ProcessUnitIDWhenLoad = false;
        }

        protected override ACCDevice CreateDevice()
        {
            ACCDevice dev = base.CreateDevice();
            if (kukaSiemensDev != null)
            {
                kukaSiemensDev.DB190 = 800;
                kukaSiemensDev.DB190_Offset = 0;
                kukaSiemensDev.DB192 = 80;
                kukaSiemensDev.DB192_PLC_Offset = 66;
                kukaSiemensDev.DB193 = 800;
                kukaSiemensDev.DB193_PLC_Offset = 34;
                kukaSiemensDev.DB193_ACC_Offset = 68;
                kukaSiemensDev.DB194 = 800;
                kukaSiemensDev.DB194_PLC_Offset = 34;
                kukaSiemensDev.DB194_PLC_Data_Offset = 124;
                //kukaSiemensDev.DB197 = 90;
                //kukaSiemensDev.DB197_PLC_Offset = 0;
                //kukaSiemensDev.DB197_ACC_Offset = 0;
                //kukaSiemensDev.DB197_PLC_Statis_Offset = 30000; //Station在同一个PLC里的第几个
                //kukaSiemensDev.DB197_PLC_Statis_Index = 0; //Station在同一个PLC里的第几个
                //kukaSiemensDev.ACC_ErrorCode_Offset = kukaSiemensDev.DB190_Offset + 998; ACC ErrorCode 写入地址
            }

            return dev;
        }

        public override void Init()
        {
            base.Init();

            if (Device is ClientDevice && kukaSiemensDev != null)
            {
                kukaSiemensDev.OnPrintLabel += new ACCDevice.DeviceRequestHandle(OnPrintLabel);
            }
        }

        public override void Uninit()
        {
            if (Device is ClientDevice && kukaSiemensDev != null)
            {
                kukaSiemensDev.OnPrintLabel -= new ACCDevice.DeviceRequestHandle(OnPrintLabel);
            }

            base.Uninit();
        }

        BomItemCfg packBomCfg = null;
        BomItemCfg gbBomCfg = null;

        protected override void GetComponents(RuningPartNo partno)
        {
            base.GetComponents(partno);

            if (partno != null)
            {
                packBomCfg = partno.BomCfg.GetBomItemCfgByIDName("PACK");
                gbBomCfg = partno.BomCfg.GetBomItemCfgByIDName("GBSN");
            }
        }

        //public override void ChangePartNo(RuningPartNo newpartno)
        //{
        //    base.ChangePartNo(newpartno);
        //    if (newpartno != null)
        //    {
        //        #region  SCADA-MES-28(国标码绑定), ONLY FOR TEST
        //        string msg = string.Empty;
        //        ACCCode rs = ACCCode.ACCOK;
        //        try
        //        {
        //            string orderNo = "000610001024";
        //            string wono = "WO-20200418-0563";
        //            string prod_sn = "2111001116000A4L0000008";
        //            string gb_sn = "053PB008000022A4L0000005";
        //            var cont = new MESGBSerialNumber()
        //            {
        //                order_code = orderNo,
        //                work_code = wono,
        //                mrl_code = "2111-00111",
        //                mrl_name = "电池包总成,YLC箱,1P36S-302Ah,35kWh",
        //                prod_sn = prod_sn,
        //                gb_sn = gb_sn,
        //                sn_type = "1"  //1-PACK国标条码，2-模组国标条码
        //            };

        //            PublishIotMessage("SCADA-MES-28", cont);

        //            StnEventLog.Log(_data, rs == ACCCode.ACCOK ? StnLog.LogType.Event : StnLog.LogType.Error,
        //                string.Format("Pack国标码{0}报工{1} Pack内码={2}, 出错信息={3}",
        //                rs == ACCCode.ACCOK ? "成功" : "失败", gb_sn, prod_sn, msg));
        //        }
        //        catch (Exception ex)
        //        {
        //            logger.Error(ex.Message, ex);
        //        }
        //        #endregion
        //    }
        //}

        public override ACCDevice.PrintResult ProcessPrintLabel(ACCDevice dev)
        {
            return new ACCDevice.PrintResult() 
            {
                 ErrorCode = ACCCode.ACCOK,
                 ReturnCode = 0,
                 ErrorMessage = string.Empty
            };
        }

        public override ACCCode SendPrintResult(ACCDevice dev, ACCDevice.PrintResult result)
        {
            string msg = string.Empty;
            //string packsn = _data.LastLoadUnit == null ? string.Empty : _data.LastLoadUnit.UnitSN;
            //var gbUnitId = _data.LastLoadUnit == null ? null : _data.LastLoadUnit.GetUnitIDByIDName("GBSN");
            //string gbsn = gbUnitId == null ? string.Empty : gbUnitId.IDValue;
            string packsn = string.Empty;
            string gbsn = string.Empty;

            if (result.ErrorCode == ACCCode.ACCOK && !string.IsNullOrEmpty(PalletNo))
            {
                string[] u = this.GetPallet(PalletNo);
                if (u != null && u.Length > 0)
                {
                    packsn = u[0];
                    gbsn = u.Length > 1 ? u[1] : string.Empty;
                }
                if (string.IsNullOrEmpty(gbsn))
                {
                    var attrs = GetOrderAttributes(OrderNo);
                    if (attrs != null && attrs.ContainsKey("CELL_TYPE") && attrs.ContainsKey("PACK_SPEC"))
                    {
                        _data.PartNo.Variables["CELL_TYPE"] = attrs["CELL_TYPE"];
                        _data.PartNo.Variables["PACK_SPEC"] = attrs["PACK_SPEC"];
                        // 053P[PARTNO,CELL_TYPE][PARTNO,PACK_SPEC]000022[CY][M][D][COUNTER,GBSN,7]
                        gbsn = PartTypeTagProcess.GetPartTypeTagValue(_data.PartNo.BomCfg, "GBSN", logger);
                    }
                    else
                    {
                        return ACCCode.UserDef_129; // 订单信息缺失，无法生成国标码
                    }
                }

                // 绑定Pallet与内部码(SN1 = Pack内部码、SN2 = 模组国标码)
                this.AddPallet(PalletNo, packsn, gbsn, string.Empty);

                // 写入Pack内码, 2 长度30 
                result.ErrorCode = SendBarcodeToPlc(new string[] { packsn }, kukaSiemensDev.DB190_Offset + 2, 30);
                // 写入国标码, 72 长度30 
                result.ErrorCode = SendBarcodeToPlc(new string[] { gbsn }, kukaSiemensDev.DB190_Offset + 72, 30);

                NotifyClientGBSN(new MESSerialNumberSync()
                                    {
                                        prod_sn = packsn,
                                        gb_sn = gbsn,
                                        sn_type = "1"
                                    });
            }
            SiemensDeviceKukaPack.ACCIndex_PrintOK = -1;
            SiemensDeviceKukaPack.ACCIndex_PrintNOK = -1;
            ACCCode rs = base.SendPrintResult(dev, result);
            if(rs == ACCCode.ACCOK && result.ErrorCode == ACCCode.ACCOK)
            {
                // 置位请求
                bool bRet = kukaSiemensDev.WriteDBBit(kukaSiemensDev.DB190, (int)kukaSiemensDev.DB190_Offset * 8 + SiemensDeviceKukaPack.CommIndex_Print, false);
                if (!bRet) rs = ACCCode.PLC_WriteError;
            }
            return rs;
        }

        public override ACCCode ReadLoadParam(ACCDevice dev, out ACCDevice.LoadParam param)
        {
            _data.Components = new BomItemCfg[] { packBomCfg };
            OrderNo = string.Empty;
            PlannedQty = 0;
            IsACCReport = false;
            ACCCode rs = base.ReadLoadParam(dev, out param);
            IsACCReport = true;

            // 强制解绑托盘
            this.RemovePallet(param.UnitSN);

            if (kukaSiemensDev == null)
            {
                StnEventLog.Log(_data, StnLog.LogType.Error, "PLC 未连接");
                return rs = ACCCode.PLC_WriteError;
            }

            // 使用托盘号关联的工站
            if (rs == ACCCode.ACCOK && !string.IsNullOrEmpty(param.UnitSN))
            {
                #region Pack内部码和国标码由ACC生成的情况
                string packBarcode = string.Empty; // Pack内部码
                //string gbBarcode = string.Empty;   // Pack国标码
                PalletNo = param.UnitSN;
                param.UnitSN = string.Empty;

                //根据托盘号获取Pack内部码   
                string[] u = this.GetPallet(PalletNo);
                if (u != null && u.Length > 0)
                {
                    param.UnitSN = packBarcode = u[0];
                    //gbBarcode = u.Length > 1 ? u[1] : string.Empty;
                }

                // 是否返工件
                var woCurrent = _womsProcess.GetCurrentWorkOrder();
                string currentWoNo = woCurrent == null || woCurrent.IsNull ? string.Empty : woCurrent.Header.WONo;
                //string orderNo = woCurrent == null || woCurrent.IsNull ? string.Empty : woCurrent.Header.PONo
                OrderNo = woCurrent == null || woCurrent.IsNull ? string.Empty : woCurrent.Header.PONo;
                string partNo = woCurrent == null || woCurrent.IsNull ? string.Empty : woCurrent.Header.PartNo;
                bool isRwk = string.IsNullOrEmpty(packBarcode) ? false : IsReworkUnitSN(packBarcode, out partNo);
                if (isRwk)
                {
                    var unit = UnitDataProcess.GetWIPUnit(_lineData, packBarcode);
                    if (unit != null)
                    {
                        partNo = unit.PartNo;

                        // 工单切换和换型
                        var wono = GetWorkOrderByUnitSN(_lineData.Line, unit.UnitSN, out OrderNo, out PlannedQty);
                        if (string.IsNullOrEmpty(wono))
                        {
                            // 获取该件的工单
                            woCurrent = _womsProcess.GetWorkOrderByPartNo(_lineData.Line, unit.PartNo);
                            wono = woCurrent.IsNull ? string.Empty : woCurrent.Header.WONo;
                            partNo = woCurrent.IsNull ? unit.PartNo : woCurrent.Header.PartNo;

                            if (string.IsNullOrEmpty(wono))
                            {
                                // 如果没有工单则获取下一个待生产工单
                                wono = GetWorkOrder(_lineData.Line, string.Empty, out partNo, out OrderNo, out PlannedQty);
                                woCurrent = _womsProcess.GetWorkOrderByWorkOrderNo(_lineData.Line, wono);
                                partNo = woCurrent.IsNull ? unit.PartNo : woCurrent.Header.PartNo;
                            }
                        }
                        else
                        {
                            woCurrent = _womsProcess.GetWorkOrderByWorkOrderNo(_lineData.Line, wono);
                            currentWoNo = wono = woCurrent.IsNull ? string.Empty : woCurrent.Header.WONo;
                            partNo = woCurrent.IsNull ? unit.PartNo : woCurrent.Header.PartNo;

                            if (string.IsNullOrEmpty(wono))
                            {
                                currentWoNo = GetNewWorkOrder(_lineData.Line, currentWoNo, unit.PartNo, out OrderNo);
                                if (!string.IsNullOrEmpty(currentWoNo))
                                {
                                    //rs = AutoChangePartNo(partNo, ref param);
                                    // 更新当前工单
                                    SetCurrentWorkOrder(currentWoNo, partNo);
                                }
                                else if (string.IsNullOrEmpty(currentWoNo))
                                {
                                    // 没有工单需要生产
                                    return rs = ACCCode.UserDef_100;
                                }
                            }
                            else
                            {
                                //rs = AutoChangePartNo(partNo, ref param);
                                // 更新当前工单
                                SetCurrentWorkOrder(currentWoNo, partNo);
                            }
                        }
                        // 当前工单和要生产的件的工单不一致，要切换工单
                        if (!string.IsNullOrEmpty(wono) && currentWoNo != wono)
                        {
                            // 切换工单
                            SetCurrentWorkOrder(wono, partNo);
                        }

                        //if (string.IsNullOrEmpty(gbBarcode) && unit.GetUnitIDByIDName("GBSN") != null)
                        //{
                        //    gbBarcode = unit.GetUnitIDByIDName("GBSN").IDValue;
                        //}

                        if (string.IsNullOrEmpty(wono))
                        {
                            // 没有工单需要生产
                            return rs = ACCCode.UserDef_100;
                        }

                        currentWoNo = wono;
                    }
                }
                // 如果工单号为空、说明还没有进行生产
                //if (string.IsNullOrEmpty(currentWoNo))
                else
                {
                    // 从下达的工单中取得一个工单
                    // 取得方法:已下达的工单（STATUS = 1）按照【SORT】字段升序排序后的第一个工单
                    string wono = GetWorkOrder(_lineData.Line, string.Empty, out partNo, out OrderNo, out PlannedQty);
                    if (!string.IsNullOrEmpty(wono) && currentWoNo != wono)
                    {
                        // 更新当前工单
                        SetCurrentWorkOrder(wono, partNo);
                    }
                    else if (string.IsNullOrEmpty(wono))
                    {
                        // 没有工单需要生产
                        return rs = ACCCode.UserDef_100;
                    }

                    currentWoNo = wono;
                }

                //rs = AutoChangePartNo(partNo, ref param);

                if (!string.IsNullOrEmpty(packBarcode))
                {
                    // 检查工单状态
                    woCurrent = _womsProcess.GetCurrentWorkOrder();
                    if (woCurrent.IsNull)
                    {
                        currentWoNo = GetWorkOrder(_lineData.Line, string.Empty, out partNo, out OrderNo, out PlannedQty);
                        if (!string.IsNullOrEmpty(currentWoNo))
                        {
                            //rs = AutoChangePartNo(partNo, ref param);
                            SetCurrentWorkOrder(currentWoNo, partNo);
                        }
                    }
                    else
                    {
                        currentWoNo = woCurrent.Header.WONo;
                        OrderNo = woCurrent.Header.PONo;
                        partNo = woCurrent.Header.PartNo;
                    }
                    rs = _womsProcess.CheckWorkOrder(true, packBarcode);
                    // 返回ACCCode.UserDef_104（工单已满）、则获取下一个工单(工单完成自动切换工单)
                    if (rs == ACCCode.UserDef_104)
                    {
                        // 从下达的工单中取得下一个工单
                        // 取得方法:已下达的工单（STATUS = 1）按照【SORT】字段升序排序、工单号不等于当前工单号的第一个工单作为下一个要生产的工单
                        currentWoNo = GetNewWorkOrder(_lineData.Line, string.Empty, currentWoNo, out partNo, out OrderNo);
                        if (!string.IsNullOrEmpty(currentWoNo))
                        {
                            //rs = AutoChangePartNo(partNo, ref param);
                            // 更新当前工单
                            SetCurrentWorkOrder(currentWoNo, partNo);
                        }
                        else if (string.IsNullOrEmpty(currentWoNo))
                        {
                            // 没有工单需要生产
                            return rs = ACCCode.UserDef_100;
                        }
                    }
                    rs = AutoChangePartNo(partNo, ref param);
                    //if (string.IsNullOrEmpty(gbBarcode) && !string.IsNullOrEmpty(orderNo))
                    //{
                    //    var attrs = GetOrderAttributes(orderNo);
                    //    if (attrs != null && attrs.ContainsKey("CELL_TYPE") && attrs.ContainsKey("PACK_SPEC"))
                    //    {
                    //        _data.PartNo.Variables["CELL_TYPE"] = attrs["CELL_TYPE"];
                    //        _data.PartNo.Variables["PACK_SPEC"] = attrs["PACK_SPEC"];
                    //        // 053P[PARTNO,CELL_TYPE][PARTNO,PACK_SPEC]000022[CY][M][D][COUNTER,GBSN,7]
                    //        gbBarcode = PartTypeTagProcess.GetPartTypeTagValue(_data.PartNo.BomCfg, "GBSN", logger);
                    //    }
                    //    else
                    //    {
                    //        return rs = ACCCode.UserDef_129; // 订单信息缺失，无法生成国标码
                    //    }
                    //}
                }
                else
                {
                    rs = AutoChangePartNo(partNo, ref param);
                    // TO-DO: 生成Pack内部码和国标码
                    packBarcode = PartTypeTagProcess.GetPartTypeTagValue(_data.PartNo.BomCfg, "PACKSN", logger).Replace("-", "");
                    //if (!string.IsNullOrEmpty(orderNo))
                    //{
                    //    var attrs = GetOrderAttributes(orderNo);
                    //    if (attrs != null && attrs.ContainsKey("CELL_TYPE") && attrs.ContainsKey("PACK_SPEC"))
                    //    {
                    //        _data.PartNo.Variables["CELL_TYPE"] = attrs["CELL_TYPE"];
                    //        _data.PartNo.Variables["PACK_SPEC"] = attrs["PACK_SPEC"];
                    //        // 053P[PARTNO,CELL_TYPE][PARTNO,PACK_SPEC]000022[CY][M][D][COUNTER,GBSN,7]
                    //        gbBarcode = PartTypeTagProcess.GetPartTypeTagValue(_data.PartNo.BomCfg, "GBSN", logger);
                    //    }
                    //    else
                    //    {
                    //        return rs = ACCCode.UserDef_129; // 订单信息缺失，无法生成国标码
                    //    }
                    //}
                }

                // 检查工单状态
                rs = _womsProcess.CheckWorkOrder(true, packBarcode);
                if (rs == ACCCode.ACCOK)
                {
                    woCurrent = _womsProcess.GetCurrentWorkOrder();
                    if (string.IsNullOrEmpty(currentWoNo))
                        currentWoNo = woCurrent.IsNull ? string.Empty : woCurrent.Header.WONo;
                    PlannedQty = woCurrent.IsNull ? 0 : woCurrent.Header.PlanQuantity;
                    if(string.IsNullOrEmpty(OrderNo))
                        OrderNo = woCurrent.IsNull ? string.Empty : woCurrent.Header.PONo;
                }
                StnEventLog.Log(_data, StnLog.LogType.Warning, "WoNo = " + currentWoNo);
                //if (rs == ACCCode.ACCOK)
                //{
                //    rs = AutoChangePartNo(partNo, ref param);
                //}

                if (rs != ACCCode.ACCOK)
                {
                    return rs;
                }

                param.UnitSN = packBarcode;
                param.ComponentSN = new string[] { };
                param.PartTypeID = _data.PartNo == null ? 0 : (int)_data.PartNo.BomCfg.PartTypeID;
                param.PartNo = _data.PartNo;
                #endregion
            }
            return rs;
        }

        public override ACCCode SendLoadResult(ACCDevice dev, ACCDevice.LoadResult result)
        {
            string msg = string.Empty;
            string packsn = _data.LastLoadUnit == null ? string.Empty : _data.LastLoadUnit.UnitSN;
            string gbsn = string.Empty;
            //var gbUnitId = _data.LastLoadUnit == null ? null : _data.LastLoadUnit.GetUnitIDByIDName("GBSN");
            //string gbsn = gbUnitId == null ? string.Empty : gbUnitId.IDValue;

            if (result.ErrorCode == ACCCode.ACCOK && !string.IsNullOrEmpty(packsn)/* && !string.IsNullOrEmpty(gbsn)*/)
            {
                // 绑定Pallet与内部码(SN1 = Pack内部码、SN2 = 模组国标码)
                this.AddPallet(PalletNo, packsn, gbsn, string.Empty);

                // 写入Pack内码, 2 长度30 
                //result.ErrorCode = SendBarcodeToPlc(new string[] { packsn }, kukaSiemensDev.DB190_Offset + 2, 30);
                // 写入国标码, 72 长度30 
                //result.ErrorCode = SendBarcodeToPlc(new string[] { gbsn }, kukaSiemensDev.DB190_Offset + 72, 30);
                // 订单型号 104， 长度10
                result.ErrorCode = SendBarcodeToPlc(new string[] { _data.LastLoadUnit.PartNo }, kukaSiemensDev.DB190_Offset + 104, 10);
                // 订单数量 116
                result.ErrorCode = SendInt16ToPlc(new int[] { PlannedQty }, kukaSiemensDev.DB190_Offset + 116);
            }

            IsACCReport = false; // 不给ACC报工
            return base.SendLoadResult(dev, result);
        }

        public override ACCCode ReadUnloadParam(ACCDevice dev, out ACCDevice.UnloadParam param)
        {
            string gbsn = string.Empty;
            IsACCReport = true;
            ACCCode rs = base.ReadUnloadParam(dev, out param);
            param.UnitSN = PalletNo = GetUnLoadPallet();
            rs = ACCCode.ACCOK;

            _data.Components = new BomItemCfg[] { packBomCfg, gbBomCfg };

            if (rs == ACCCode.ACCOK && !string.IsNullOrEmpty(PalletNo))
            {
                // 通过pallet 获取内部码
                string[] v = this.GetPallet(PalletNo);
                if (v != null && v.Length > 0)
                {
                    param.UnitSN = v[0];
                    gbsn = v.Length > 1 ? v[1] : string.Empty;

                }
                param.ComponentSN = new string[] { gbsn/*GetGBSN(param.UnitSN, _lineData.Line, "GBSN")*/ };
            }

            logger.Debug(string.Format("PACK = '{0}',GBSN = '{1}'", param.UnitSN, param.ComponentSN.Length > 0 ? param.ComponentSN[0] : string.Empty));
            return rs;
        }
        public string GetUnLoadPallet()
        {
            string pallet = "";
            try
            {
                byte[] data = new byte[32];
                byte[] temp = new byte[30];
                kukaSiemensDev.ReadDBBytes(kukaSiemensDev.DB194, kukaSiemensDev.DB194_PLC_Offset, data);
                Array.Copy(data, 2, temp, 0, temp.Length);
                pallet = Encoding.ASCII.GetString(temp);
                if (pallet != null && pallet.Length > data[1])
                {
                    pallet = pallet.Substring(0, data[1]);
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex.StackTrace);
            }
            return pallet;
        }
    }
}